"""Contains classes pertaining the the representation of the game board."""
import exceptions

class BreakLoop:
	"""Class used to break out of loops by throwing as an exception."""
	def __init__(self,args=None):
		self.args=args

class BoardError(exceptions.Exception):
	"""Exception class for Board."""
	def __init__(self,args=None):
		self.args=args

class Board:
	"""Represents game board.
	Does not enforce any game rules.  Used only for board representation."""
	def __init__(self):
		"""Creates an empty board.
		Creates empty list to represent board.  Sets move count to 0.
		Sets moves stack to empty.
		
		NOT LARGER BOARD COMPATIBLE!
		
		"""
		self.board=[]
		for row_cnt in range(3):
			col=[]
			for col_cnt in range(3):
				col.append(None)
			self.board.append(col)
		self.move_count=0
		self.moves=[]

	def makeMove(self,coords,player):
		"""Makes the passed-in move.
		There is no checking to see if player is a valid avatar.
		
		"""
		position=self.board
		for axis in coords[:-1]:
			position=position[axis]
		if position[coords[-1]]: raise BoardError,'A piece is already in that position'
		else:
			position[coords[-1]]=player
			self.move_count+=1
			self.moves.append((coords,player))

	def moveCount(self):
		"""Returns the number of moves made."""
		return self.move_count

	def rollbackMove(self):
		"""Sets game state back one move."""
		try:
			last_move=self.moves[-1]
			position=self.board
			for axis in last_move[0][:-1]:
				position=position[axis]
			position[last_move[0][-1]]=None
			self.moves=self.moves[:-1]
			self.move_count-=1
		except IndexError: raise BoardError,'Cannot rollback any farther'	

	def canRollback(self):
		"""True if can rollback board, otherwise false."""
		if self.moves: return 1
		else: return 0

	def copy(self):
		"""Returns an exact copy of this object."""
		board_copy=Board()
		board_copy.board=self.board[:]
		board_copy.move_count=self.move_count
		board_copy.moves=self.moves[:]
		return board_copy

	def size(self):
		"""Returns the board's dimensions."""
		dimensions=[]
		try:
			current_thing=self.board
			while 1:
				dimensions.append(len(current_thing))
				current_thing=current_thing[0]
		except TypeError:
			return tuple(dimensions)

	def _checkLine(self,line):
		"""Returns 1 if someone won on this line, 0 if a move is still possible, and -1 if the line leads to a Cat's Game."""
		try:
			first_avatar=line[:]
			try:
				while 1: first_avatar.remove(None)
			except ValueError: pass
			first_avatar=first_avatar[0]
		except: return 0
		for avatar in line:
			if avatar==first_avatar: continue
			elif avatar==None: continue
			else: break
		else:
			if None in line: return 0
			else: return 1
		return -1
	
	def status(self):
		"""Returns tuple stating whether the game is over (and if so who won or if it's a Cat's Game) or if a move is still possible.
		The returned two-part tuple has index 0 indicating whether 
		someone has won (1), a move is still possible (0), or if it is a
		Cat's Game (-1).  Index 2 indicates who won (if there is a 
		winner).

		NOT LARGER BOARD COMPATIBLE!
		
		"""
		status=-1
		avatar=None
		line=[]
		try:
			for row in range(3):
				for col in range(3):
					line.append(self.board[row][col])
				result=self._checkLine(line)
				if result==1: raise BreakLoop,line[0]
				elif result==0: status=0
				line=[]
			for col in range(3):
				for row in range(3):
					line.append(self.board[row][col])
				result=self._checkLine(line)
				if result==1: raise BreakLoop, line[0]
				elif result==0: status=0
				line=[]
			for cnt in range(3):
				line.append(self.board[cnt][cnt])
			result=self._checkLine(line)
			if result==1: raise BreakLoop,line[0]
			elif result==0: status=0
			line=[]
			for cnt in range(3):
				line.append(self.board[cnt][2-cnt])
			result=self._checkLine(line)
			if result==1: raise BreakLoop,line[0]
			elif result==0: status=0
		except BreakLoop,who_won: return (1,who_won.args)
		else: return (status,None)





